package com.hgyc.mom.mes.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hgyc.mom.base.entity.Material;
import com.hgyc.mom.base.service.MaterialService;
import com.hgyc.mom.common.config.MinioConfig;
import com.hgyc.mom.common.constant.CacheConstants;
import com.hgyc.mom.common.enums.CommonStatus;
import com.hgyc.mom.common.exception.BizException;
import com.hgyc.mom.common.redis.RedisCache;
import com.hgyc.mom.mes.entity.*;
import com.hgyc.mom.mes.enums.SopDocumentStatusEnum;
import com.hgyc.mom.mes.mapper.SopDocumentManageMapper;
import com.hgyc.mom.mes.service.*;
import com.hgyc.mom.mes.vo.LineInProductVO;
import com.hgyc.mom.mes.vo.SopDocumentManageVO;
import com.hgyc.mom.mes.websocket.util.WebSocketUsers;
import com.hgyc.mom.system.service.SysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 文档集Service业务层实现
 *
 * @author fwj
 * @since 2025-06-18
 */
@Slf4j
@Service
public class SopDocumentManageServiceImpl extends ServiceImpl<SopDocumentManageMapper, SopDocumentManage> implements SopDocumentManageService {

    public final static List<String> videoExtensions = Arrays.asList("mp4", "mov", "avi", "mkv", "flv", "wmv", "webm");
    public final static List<String> imageExtensions = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp", "tiff", "webp", "svg");

    @Autowired
    private SopDocumentService sopDocumentService;
    @Autowired
    private SopDocumentProductService sopDocumentProductService;
    @Autowired
    private SopAttachmentService sopAttachmentService;
    @Autowired
    private SopTerminalService  sopTerminalService;

    @Autowired
    private MesWorkshopService  mesWorkshopService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private SopSendRecordService sopSendRecordService;

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private MaterialService materialService;

    @Autowired
    private MinioConfig minioConfig;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveManage(SopDocumentManageVO sopDocumentManageVO) {
        // TODO 其他逻辑
        save(sopDocumentManageVO);

        //新增文档管理
        List<SopDocument> documents = sopDocumentManageVO.getAddDocuments();
        if (!CollectionUtils.isEmpty(documents)) {
            documents.forEach(item -> {
                item.setId(null);
                item.setManageId(sopDocumentManageVO.getId());
            });
            sopDocumentService.saveBatch(documents);
        }
        //新增关联产品
        List<SopDocumentProduct> products = sopDocumentManageVO.getAddProducts();
        if (!CollectionUtils.isEmpty(products)) {
            products.forEach(item -> {
                item.setId(null);
                item.setManageId(sopDocumentManageVO.getId());
            });
            sopDocumentProductService.saveBatch(products);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateManage(SopDocumentManageVO sopDocumentManageVO) {
        // TODO 其他逻辑
        updateById(sopDocumentManageVO);

        //删除文档管理
        if (!CollectionUtils.isEmpty(sopDocumentManageVO.getDeleteDocumentIds())) {
            sopDocumentService.removeBatchByIds(sopDocumentManageVO.getDeleteDocumentIds());
        }

        //新增文档管理
        List<SopDocument> documents = sopDocumentManageVO.getAddDocuments();
        if (!CollectionUtils.isEmpty(documents)) {
            documents.forEach(item -> {
                item.setId(null);
                item.setManageId(sopDocumentManageVO.getId());
            });
            sopDocumentService.saveBatch(documents);
        }

        //更新文档管理
        if (!CollectionUtils.isEmpty(sopDocumentManageVO.getUpdateDocuments())) {
            List<SopDocument> updateDocuments = sopDocumentManageVO.getUpdateDocuments();
            sopDocumentService.updateBatchById(updateDocuments);
        }
        //删除关联产品
        if (!CollectionUtils.isEmpty(sopDocumentManageVO.getDeleteProductIds())) {
            sopDocumentProductService.removeBatchByIds(sopDocumentManageVO.getDeleteProductIds());
        }

        //新增关联产品
        List<SopDocumentProduct> products = sopDocumentManageVO.getAddProducts();
        if (!CollectionUtils.isEmpty(products)) {
            products.forEach(item -> {
                item.setId(null);
                item.setManageId(sopDocumentManageVO.getId());
            });
            sopDocumentProductService.saveBatch(products);
        }

        //更新关联产品
        if (!CollectionUtils.isEmpty(sopDocumentManageVO.getUpdateProducts())) {
            List<SopDocumentProduct> updateProducts = sopDocumentManageVO.getUpdateProducts();
            sopDocumentProductService.updateBatchById(updateProducts);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeManage(List<Long> ids) {
        // TODO 其他逻辑
        removeByIds(ids);
        //删除文档管理
        sopDocumentService.deleteBatchByParentIds(ids);
        //删除关联产品
        sopDocumentProductService.deleteBatchByParentIds(ids);
    }

    @Override
    public void updateStatus(String status, List<Long> ids) {
        LambdaUpdateWrapper<SopDocumentManage> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.set(SopDocumentManage::getStatus, status);
        updateWrapper.in(SopDocumentManage::getId, ids);
        baseMapper.update(updateWrapper);
    }

    @Override
    public Map<String, Object> getSopInfo(String ip) {
        Map<String, Object> sopInfo = new HashMap<>();
        sopInfo.put("ip", ip);

        SopTerminal sopTerminal = sopTerminalService.getByIp(ip);
        //终端信息
        if (sopTerminal != null) {
            //车间
            Long workshopId = sopTerminal.getWorkshopId();
            MesWorkshop workshop = mesWorkshopService.getById(workshopId);
            if (workshop != null) {
                sopInfo.put("workshopName", workshop.getName());
            }
            //产线
            Long lineId = sopTerminal.getLineId();
            MesWorkshop line = mesWorkshopService.getById(lineId);
            if (line != null) {
                sopInfo.put("lineName", line.getName());
            }
            //工位
            Long stationId = sopTerminal.getStationId();
            MesWorkshop station = mesWorkshopService.getById(stationId);
            if (station != null) {
                sopInfo.put("stationName", station.getName());
            }
            sopInfo.put("reporting", sopTerminal.getReporting());

            //在产产品
            LineInProductVO lineInProductVO = redisCache.getCacheObject(CacheConstants.LINE_IN_PRODUCT_DATA_CACHE + sopTerminal.getLineId(), LineInProductVO.class);
            if (lineInProductVO != null && lineInProductVO.getMaterialId() != null) {
                sopInfo.put("materialName", lineInProductVO.getMaterialCode());
                sopInfo.put("materialCode", lineInProductVO.getMaterialName());
                sopInfo.put("materialSpec", lineInProductVO.getMaterialSpec());
            }
        }


        //系统配置
        sopInfo.put("sysConfig", getSysConfig());

        return sopInfo;
    }

    //旧接口
    @Override
    public Map<String, Object> getDocByIp(String ip) {
        LambdaQueryWrapper<SopTerminal> qw = new LambdaQueryWrapper<SopTerminal>()
                .eq(SopTerminal::getIp, ip)
                .orderByDesc(SopTerminal::getCreateTime)
                .last("LIMIT 1");
        SopTerminal sopTerminal = sopTerminalService.getOne(qw);
        if (Objects.isNull(sopTerminal)) {
            throw new BizException("没有找到此IP：["+ip+"]的终端！");
        }
        LambdaQueryWrapper<SopSendRecord> recordWrapper = new LambdaQueryWrapper<SopSendRecord>()
                .eq(SopSendRecord::getIp, ip)
                .orderByDesc(SopSendRecord::getCreateTime)
                .last("LIMIT 1");;
        SopSendRecord sopSendRecord = sopSendRecordService.getOne(recordWrapper);
        if (Objects.isNull(sopSendRecord)){
            throw new BizException("没有找到此IP：["+ip+"]的推送记录！");
        }

        SopDocumentManage sopDocumentManage = getById(sopSendRecord.getManageId());
        if (!Objects.isNull(sopDocumentManage) && !SopDocumentStatusEnum.PUBLISHED.getValue().equals(sopDocumentManage.getStatus())) {
            throw new BizException("该文档所属文档集不是已发布状态！");
        }

        Map<String, Object> sysConfig = getSysConfig();

        SopDocument sopDocument = sopDocumentService.getById(sopSendRecord.getDocumentId());

        if (sopDocument != null) {
            Map<String, Object> res = new HashMap<>();

            //文档信息
            Long attachmentId = sopDocument.getAttachmentId();
            SopAttachment sopAttachment = sopAttachmentService.getById(attachmentId);
            res.put("fileName", sopAttachment.getFileName());
            res.put("fileType", sopAttachment.getFileType());
            res.put("attachmentId", sopAttachment.getId());

            //车间
            Long workshopId = sopTerminal.getWorkshopId();
            MesWorkshop workshop = mesWorkshopService.getById(workshopId);
            if (workshop != null) {
                res.put("workshopName", workshop.getName());
            }
            //产线
            Long lineId = sopTerminal.getLineId();
            MesWorkshop line = mesWorkshopService.getById(lineId);
            if (line != null) {
                res.put("lineName", line.getName());
            }
            //工位
            Long stationId = sopTerminal.getStationId();
            MesWorkshop station = mesWorkshopService.getById(stationId);
            if (station != null) {
                res.put("stationName", station.getName());
            }
            res.put("reporting", sopTerminal.getReporting());

            //产品信息
            if (sopSendRecord.getMaterialId() != null) {
                Material material = materialService.getById(sopSendRecord.getMaterialId());
                res.put("materialName", material.getMaterialName());
                res.put("materialSpec", material.getSpec());
            }

            res.put("config", sysConfig);

            if (videoExtensions.contains(sopAttachment.getFileType()) || imageExtensions.contains(sopAttachment.getFileType())) {
                return res;
            } else {
                List<SopAttachment> imagesAttachments = sopAttachmentService.getByParentId(sopAttachment.getId());

                List<Long> idList = imagesAttachments.stream().map(SopAttachment::getId).collect(Collectors.toList());

                Integer startIndex = sopDocument.getStartIndex();
                Integer endIndex = sopDocument.getEndIndex();

                // 处理 startCursor 为空的情况，默认为 1
                startIndex = (startIndex != null) ? startIndex - 1 : 0;
                // 处理 endCursor 为空的情况，默认为 list.size()
                endIndex = (endIndex != null) ? endIndex : idList.size();
                // **确保索引合法**
                startIndex = Math.max(0, startIndex);  // 防止负数
                endIndex = Math.min(idList.size(), endIndex);  // 防止超出 list.size()


                res.put("imageList", idList.subList(startIndex, endIndex));

                return res;
            }
        }

        return null;
    }

    private Map<String, Object> getSysConfig() {
        Map<String, Object> sysConfig = new HashMap<>();
        sysConfig.put("cycleTime", Integer.valueOf(sysConfigService.selectConfigByKey("sop.cycleTime")) * 1000);
        sysConfig.put("radioPlayType", sysConfigService.selectConfigByKey("sop.radioPlayType"));
        sysConfig.put("fileSize", Integer.valueOf(sysConfigService.selectConfigByKey("sop.fileSize")));
        sysConfig.put("flushRate", Integer.valueOf(sysConfigService.selectConfigByKey("sop.flushRate")) * 1000);
        sysConfig.put("isAutoPageTurning", Boolean.parseBoolean(sysConfigService.selectConfigByKey("sop.autoPageTurning")));
        sysConfig.put("haveProducingOrder", true);
        return sysConfig;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendMultipleDoc(List<SopSendRecord> sendRecords) {
        //系统配置
        Map<String, Object> sysConfig = getSysConfig();

        // 1. 按 IP 分组
        Map<String, List<SopSendRecord>> groupedByIP = sendRecords.stream()
                .collect(Collectors.groupingBy(SopSendRecord::getIp));

        // 2. 之前的推送记录失效
        groupedByIP.forEach((key, value) -> {
            sopSendRecordService.invalidByIp(key);
        });

        groupedByIP.forEach((key, recordList) -> {
            Map<String, Object> sendReocrdMap = new HashMap<>();
            sendReocrdMap.put("sysConfig", sysConfig);

            //文件列表
            List<Map<String, Object>> docInfoList = new ArrayList<>();
            recordList.forEach(sopSendRecord -> {
                SopDocument sopDocument = sopDocumentService.getById(sopSendRecord.getDocumentId());

                if (sopDocument != null) {
                    //文档信息
                    Long attachmentId = sopDocument.getAttachmentId();
                    SopAttachment sopAttachment = sopAttachmentService.getById(attachmentId);
                    if (sopAttachment != null) {
                        // 更新记录
                        sopSendRecord.setFileUrl(sopAttachment.getFileUrl());

                        if (videoExtensions.contains(sopAttachment.getFileType()) || imageExtensions.contains(sopAttachment.getFileType())) {
                            Map<String, Object> documentMap = document2Map(sopAttachment);
                            docInfoList.add(documentMap);
                        } else {
                            List<SopAttachment> imagesAttachments = sopAttachmentService.getByParentId(sopDocument.getAttachmentId());

                            Integer startIndex = sopDocument.getStartIndex();
                            Integer endIndex = sopDocument.getEndIndex();

                            // 处理 startIndex 为空的情况，默认为 1
                            startIndex = (startIndex != null) ? startIndex - 1 : 0;
                            // 处理 endIndex 为空的情况，默认为 list.size()
                            endIndex = (endIndex != null) ? endIndex : imagesAttachments.size();
                            // **确保索引合法**
                            startIndex = Math.max(0, startIndex);  // 防止负数
                            endIndex = Math.min(imagesAttachments.size(), endIndex);  // 防止超出 list.size()

                            List<SopAttachment> subList = imagesAttachments.subList(startIndex, endIndex);
                            subList.forEach(attachment -> {
                                Map<String, Object> showDocMap = document2Map(attachment);
                                docInfoList.add(showDocMap);
                            });
                        }
                    }
                }
            });
            sendReocrdMap.put("docList", docInfoList);

            ObjectMapper mapper = new ObjectMapper();
            try {
                WebSocketUsers.sendMessageToUser(key, mapper.writeValueAsString(sendReocrdMap));
            } catch (JsonProcessingException e) {
                throw new BizException("发送文档到设备终端失败！");
            }
        });

        sopSendRecordService.saveBatch(sendRecords);
    }

    @Override
    public Map<String, Object> getMultipleDocByIp(String ip) {
        Map<String, Object> res = new HashMap<>();

        SopTerminal sopTerminal = sopTerminalService.getByIp(ip);
        if (Objects.isNull(sopTerminal)) {
            throw new BizException("没有找到此IP：["+ip+"]的终端！");
        }

        LambdaQueryWrapper<SopSendRecord> recordWrapper = new LambdaQueryWrapper<SopSendRecord>()
                .eq(SopSendRecord::getIp, ip)
                .eq(SopSendRecord::getStatus, CommonStatus.ENABLE.getValue())
                .orderByAsc(SopSendRecord::getCreateTime);

        List<SopSendRecord> recordList = sopSendRecordService.list(recordWrapper);
        if (CollectionUtils.isEmpty(recordList)) {
            throw new BizException("没有找到此IP：["+ip+"]的推送记录！");
        }

        //系统配置
        res.put("sysConfig", getSysConfig());

        //文件列表
        List<Map<String, Object>> docInfoList = new ArrayList<>();
        recordList.forEach(sopSendRecord -> {
            SopDocument sopDocument = sopDocumentService.getById(sopSendRecord.getDocumentId());

            if (sopDocument != null) {
                //文档信息
                Long attachmentId = sopDocument.getAttachmentId();
                SopAttachment sopAttachment = sopAttachmentService.getById(attachmentId);
                if (videoExtensions.contains(sopAttachment.getFileType()) || imageExtensions.contains(sopAttachment.getFileType())) {
                    Map<String, Object> documentMap = document2Map(sopAttachment);
                    docInfoList.add(documentMap);
                } else {
                    List<SopAttachment> imagesAttachments = sopAttachmentService.getByParentId(sopDocument.getAttachmentId());

                    Integer startIndex = sopDocument.getStartIndex();
                    Integer endIndex = sopDocument.getEndIndex();

                    // 处理 startIndex 为空的情况，默认为 1
                    startIndex = (startIndex != null) ? startIndex - 1 : 0;
                    // 处理 endIndex 为空的情况，默认为 list.size()
                    endIndex = (endIndex != null) ? endIndex : imagesAttachments.size();
                    // **确保索引合法**
                    startIndex = Math.max(0, startIndex);  // 防止负数
                    endIndex = Math.min(imagesAttachments.size(), endIndex);  // 防止超出 list.size()

                    List<SopAttachment> subList = imagesAttachments.subList(startIndex, endIndex);
                    subList.forEach(attachment -> {
                        Map<String, Object> showDocMap = document2Map(attachment);
                        docInfoList.add(showDocMap);
                    });
                }
            }
        });
        res.put("docList", docInfoList);

        return res;
    }

    /**
     * 文件转换
     * @param sopAttachment 文件信息
     * @return map
     */
    private Map<String, Object> document2Map(SopAttachment sopAttachment) {
        Map<String, Object> docInfo = new HashMap<>();

        docInfo.put("fileName", sopAttachment.getFileName());
        docInfo.put("fileType", sopAttachment.getFileType());
        docInfo.put("attachmentId", sopAttachment.getId());
        docInfo.put("filePath", sopAttachment.getFileUrl());

        return docInfo;
    }
}
